package com.lamp.downloadimage;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.util.Log;
import android.widget.ImageView;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;

import com.lamp.main.R;

import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.WeakReference;
import java.util.LinkedList;

public class ImageDownloader {

	BitmapCache bitmapCache;
	private BitmapDownloaderTask loaderTask;
	private LinkedList<BitmapDownloaderTask> pendingTasks = new LinkedList<BitmapDownloaderTask>();
	
	
	public ImageDownloader(BitmapCache bitmapCache) {
		this.bitmapCache = bitmapCache;
	}


	public void download(String url, ImageView imageView) {

		Bitmap bitmap = bitmapCache.getBitmapFromCache(url);

		if (bitmap == null) {
			forceDownload(url, imageView);
		} else {
			removePotentialDownload(url, imageView);
			imageView.setImageBitmap(bitmap);
		}
	}

	private void forceDownload(String url, ImageView imageView) {

		if (url == null) {
			imageView.setImageDrawable(null);
			return;
		}

		if (removePotentialDownload(url, imageView)) {
			BitmapDownloaderTask task = new BitmapDownloaderTask(url, imageView);
			imageView.setTag(new WeakReference<BitmapDownloaderTask>(task));

			imageView.setMinimumHeight(156);

			pendingTasks.offer(task);
			if (loaderTask == null
					|| loaderTask.getStatus() == AsyncTask.Status.FINISHED) {
				loaderTask = pendingTasks.poll();
				loaderTask.execute();
			}
		}
	}

	private boolean removePotentialDownload(String url, ImageView imageView) {
		BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView);

		if (bitmapDownloaderTask != null) {
			String bitmapUrl = bitmapDownloaderTask.url;
			if ((bitmapUrl == null) || (!bitmapUrl.equals(url))) {
				pendingTasks.remove(bitmapDownloaderTask);
			} else {
				return false;
			}
		}
		return true;
	}

	@SuppressWarnings("unchecked")
	private static BitmapDownloaderTask getBitmapDownloaderTask(
			ImageView imageView) {
		if (imageView != null) {
			Object ref = imageView.getTag();
			if (ref != null && ref instanceof WeakReference) {
				WeakReference<BitmapDownloaderTask> taskReference = (WeakReference<BitmapDownloaderTask>) ref;
				return taskReference.get();
			}
		}
		return null;
	}

	Bitmap downloadBitmap(String url) {

		HttpClient client = HttpClientFactory.getThreadSafeClient();
		final HttpGet getRequest = new HttpGet(url);

		try {
			HttpResponse response = client.execute(getRequest);
			final int statusCode = response.getStatusLine().getStatusCode();
			if (statusCode != HttpStatus.SC_OK) {
				Log.w("ImageDownloader", "Error " + statusCode
						+ " while retrieving bitmap from " + url);
				return null;
			}

			final HttpEntity entity = response.getEntity();
			if (entity != null) {
				InputStream inputStream = null;
				try {
					inputStream = entity.getContent();
					// return BitmapFactory.decodeStream(inputStream);
					return BitmapFactory.decodeStream(new FlushedInputStream(
							inputStream));
				} finally {
					if (inputStream != null) {
						inputStream.close();
					}
					entity.consumeContent();
				}
			}
		} catch (IOException e) {
			getRequest.abort();
			Log.w("ImageDownloader", "no connection" + url, e);
		} catch (IllegalStateException e) {
			getRequest.abort();
			Log.w("ImageDownloader", "wrong URL: " + url);
		} catch (Exception e) {
			getRequest.abort();
			Log.w("ImageDownloader", "" + url, e);
		}
		return null;
	}

	static class FlushedInputStream extends FilterInputStream {
		public FlushedInputStream(InputStream inputStream) {
			super(inputStream);
		}

		@Override
		public long skip(long n) throws IOException {
			long totalBytesSkipped = 0L;
			while (totalBytesSkipped < n) {
				long bytesSkipped = in.skip(n - totalBytesSkipped);
				if (bytesSkipped == 0L) {
					int b = read();
					if (b < 0) {
						break;
					} else {
						bytesSkipped = 1;
					}
				}
				totalBytesSkipped += bytesSkipped;
			}
			return totalBytesSkipped;
		}
	}

	/**
	 * The actual AsyncTask that will asynchronously download the image.
	 */
	class BitmapDownloaderTask extends AsyncTask<Void, Void, Bitmap> {
		private String url;
		private final WeakReference<ImageView> imageViewReference;

		public BitmapDownloaderTask(String url, ImageView imageView) {
			imageViewReference = new WeakReference<ImageView>(imageView);
			this.url = url;
		}

		/**
		 * Actual download method.
		 */
		@Override
		protected Bitmap doInBackground(Void... params) {
			ImageView image = imageViewReference.get();
			if (image != null && this == getBitmapDownloaderTask(image)) {
				return downloadBitmap(url);
			} else {
				return null;
			}
		}

		/**
		 * Once the image is downloaded, associates it to the imageView
		 */
		@Override
		protected void onPostExecute(Bitmap bitmap) {
			if (isCancelled() || bitmap == null) {
				bitmap = null;
			}

			bitmapCache.addBitmapToCache(url, bitmap);

			if (imageViewReference != null) {
				ImageView imageView = imageViewReference.get();
				BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView);
				if (this == bitmapDownloaderTask) {
					
						imageView.setImageBitmap(bitmap);
					
				}
			}

			if (!pendingTasks.isEmpty()) {
				loaderTask = pendingTasks.poll();
				loaderTask.execute();
			}

		}
	}


}
